﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace SlamCms.DomainEvents
{
    public class DefaultEventDispatcher : IEventDispatcher
    {
		protected readonly IList<object> Handlers = new List<object>();

        public virtual void Dispatch<T>(T argument) where T : IDomainEvent
        {
			var eventContext = new EventContext<T>(argument);

			var handlers = GetHandlers<T>().ToArray();
			foreach (var handler in handlers)
				handler.Handle(eventContext);
        }

		public virtual void AddHandler<T>(Action<EventContext<T>> handler) where T : IDomainEvent
		{
			Handlers.Add(new ActionDomainEventHandler<T>(handler));
		}

		public virtual void AddHandler<T>(IDomainEventHandler<T> handler) where T : IDomainEvent
		{
			Handlers.Add(handler);
		}

		public virtual void ClearHandlers()
		{
			Handlers.Clear();
		}

		public virtual void ClearHandlers<T>() where T : IDomainEvent
		{
			var handlers = GetHandlers<T>().ToArray();
			foreach (var handler in handlers)
				Handlers.Remove(handler);
		}

		protected virtual IEnumerable<IDomainEventHandler<T>> GetHandlers<T>() where T : IDomainEvent
		{
			foreach (var handler in Handlers)
			{
				if (handler is IDomainEventHandler<T>)
					yield return (IDomainEventHandler<T>)handler;
			}
		}
    }
}
